const express = require("express");
const WebSocket = require("ws");
const http = require("http");
const cors = require("cors");
const { v4: uuidv4 } = require("uuid");

// 创建Express应用
const app = express();
const server = http.createServer(app);

// 中间件配置
app.use(cors());
app.use(express.json());
app.use(express.static("../frontend")); // 提供前端静态文件

// 存储直播间信息
const rooms = new Map();
const clients = new Map();

// 创建WebSocket服务器 - 修复配置
const wss = new WebSocket.Server({
  server,
  path: "/ws",
  // 移除可能导致问题的配置
  //   perMessageDeflate: false, // 禁用压缩以避免frame header问题
  verifyClient: (info) => {
    console.log("=== WebSocket握手验证 ===");
    console.log("验证时间:", new Date().toISOString());
    console.log("请求详情:", {
      origin: info.origin,
      secure: info.secure,
      method: info.req.method,
      url: info.req.url,
      headers: {
        upgrade: info.req.headers.upgrade,
        connection: info.req.headers.connection,
        "sec-websocket-key": info.req.headers["sec-websocket-key"],
        "sec-websocket-version": info.req.headers["sec-websocket-version"],
      },
    });
    console.log("验证结果: 通过");
    return true; // 验证通过
  },
});

// 监听WebSocket服务器事件
wss.on("listening", () => {
  console.log("WebSocket服务器开始监听");
});

wss.on("error", (error) => {
  console.error("WebSocket服务器错误:", error);
});

wss.on("headers", (headers, req) => {
  console.log("WebSocket握手响应头:", headers);
});

// 聊天功能集成到主WebSocket服务器中，通过消息类型区分

// WebRTC信令处理 - 修复版本
wss.on("connection", (ws, req) => {
  console.log("===== WebSocket新连接 =====");
  console.log("连接时间:", new Date().toISOString());
  console.log("连接状态:", ws.readyState);
  console.log("来源URL:", req.url);

  const clientId = Math.random().toString(36).substr(2, 9);
  console.log(`分配客户端ID: ${clientId}`);

  // 简化客户端存储
  clients.set(clientId, {
    ws: ws,
    rooms: new Set(),
    connectTime: new Date(),
  });

  console.log(`客户端连接成功: ${clientId}，当前连接数: ${clients.size}`);

  // 直接发送连接确认消息，不使用setImmediate
  try {
    const welcomeMessage = JSON.stringify({
      type: "connected",
      clientId: clientId,
      message: "连接成功",
      serverTime: new Date().toISOString(),
    });

    ws.send(welcomeMessage);
    console.log(`连接确认消息已发送: ${clientId}`);
  } catch (error) {
    console.error(`发送连接确认失败 [${clientId}]:`, error.message);
    // 如果发送失败，关闭连接
    ws.close(1011, "服务器错误");
    clients.delete(clientId);
    return;
  }

  ws.on("message", (data) => {
    try {
      console.log(`收到消息 [${clientId}]:`, data.toString());

      // 验证数据格式
      if (!data || data.length === 0) {
        console.error(`收到空消息 [${clientId}]`);
        return;
      }

      const message = JSON.parse(data);

      // 简化消息处理 - 不使用async/await
      handleWebRTCMessage(clientId, message);
    } catch (error) {
      console.error(`处理消息失败 [${clientId}]:`, error.message);
      // 发送错误响应而不是关闭连接
      try {
        ws.send(
          JSON.stringify({
            type: "error",
            error: "消息格式错误",
            details: error.message,
          })
        );
      } catch (sendError) {
        console.error(`发送错误响应失败 [${clientId}]:`, sendError.message);
      }
    }
  });

  ws.on("close", (code, reason) => {
    const connectTime = clients.get(clientId)?.connectTime;
    const duration = connectTime ? Date.now() - connectTime.getTime() : 0;

    console.log("===== WebSocket连接关闭 =====");
    console.log(`客户端ID: ${clientId}`);
    console.log(`关闭代码: ${code}`);
    console.log(`关闭原因: "${reason}"`);
    console.log(`连接持续时间: ${duration}ms`);
    console.log(`关闭时间: ${new Date().toISOString()}`);

    handleClientDisconnect(clientId);
    clients.delete(clientId);
  });

  ws.on("error", (error) => {
    console.error(`WebSocket错误 [${clientId}]:`, error.message);
    console.error("错误堆栈:", error.stack);

    // 清理客户端
    handleClientDisconnect(clientId);
    clients.delete(clientId);
  });

  // 添加ping/pong心跳机制
  ws.isAlive = true;
  ws.on("pong", () => {
    ws.isAlive = true;
  });
});

// 添加心跳检测
const heartbeat = setInterval(() => {
  wss.clients.forEach((ws) => {
    if (ws.isAlive === false) {
      console.log("检测到僵尸连接，正在终止");
      return ws.terminate();
    }

    ws.isAlive = false;
    ws.ping();
  });
}, 30000);

wss.on("close", () => {
  clearInterval(heartbeat);
});

// 聊天WebSocket处理
// chatWss.on("connection", (ws) => {
//   const clientId = uuidv4();
//   console.log(`聊天客户端连接: ${clientId}`);

//   ws.on("message", (data) => {
//     try {
//       const message = JSON.parse(data);
//       handleChatMessage(clientId, message, ws);
//     } catch (error) {
//       console.error("处理聊天消息失败:", error);
//     }
//   });

//   ws.on("close", () => {
//     console.log(`聊天客户端断开连接: ${clientId}`);
//   });
// });

// 处理WebRTC信令消息 - 修复版本
function handleWebRTCMessage(clientId, message) {
  const client = clients.get(clientId);
  if (!client || client.ws.readyState !== WebSocket.OPEN) {
    console.log(`客户端不可用或连接已关闭: ${clientId}`);
    return;
  }

  console.log(`处理消息 [${clientId}]:`, message.type);

  try {
    switch (message.type) {
      case "test":
        // 处理测试消息 - 简单回复
        console.log(`收到测试消息 [${clientId}]:`, message);
        const testResponse = {
          type: "test-response",
          message: "服务器收到测试消息: " + (message.message || ""),
          timestamp: new Date().toISOString(),
          clientId: clientId,
        };
        safeSend(client.ws, clientId, testResponse);
        break;

      case "ping":
        // 处理心跳消息
        console.log(`收到心跳 [${clientId}]:`, message.timestamp);
        const pongResponse = {
          type: "pong",
          timestamp: Date.now(),
          originalTimestamp: message.timestamp,
          clientId: clientId,
        };
        safeSend(client.ws, clientId, pongResponse);
        break;

      case "start-stream":
        handleStartStream(clientId, message);
        break;
      case "join-stream":
        handleJoinStream(clientId, message);
        break;
      case "offer":
        handleOffer(clientId, message);
        break;
      case "answer":
        handleAnswer(clientId, message);
        break;
      case "ice-candidate":
        handleIceCandidate(clientId, message);
        break;
      case "stop-stream":
        handleStopStream(clientId, message);
        break;
      case "leave-stream":
        handleLeaveStream(clientId, message);
        break;

      case "chat-message":
        handleChatMessage(clientId, message);
        break;

      default:
        console.log("未知消息类型:", message.type);
        // 简单记录，不发送响应
        break;
    }
  } catch (error) {
    console.error(`处理消息异常 [${clientId}]:`, error.message);
    // 发送错误响应
    try {
      if (client.ws.readyState === WebSocket.OPEN) {
        client.ws.send(
          JSON.stringify({
            type: "error",
            error: "处理消息时发生错误",
            details: error.message,
          })
        );
      }
    } catch (sendError) {
      console.error(`发送错误响应失败 [${clientId}]:`, sendError.message);
    }
  }
}

// 安全发送消息的辅助函数
function safeSend(ws, clientId, data) {
  try {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(data));
      return true;
    } else {
      console.log(`无法发送消息，连接状态: ${ws.readyState} [${clientId}]`);
      return false;
    }
  } catch (error) {
    console.error(`发送消息失败 [${clientId}]:`, error.message);
    return false;
  }
}

// 开始直播
function handleStartStream(clientId, message) {
  const streamId = message.streamId || uuidv4();
  const client = clients.get(clientId);

  if (!client) {
    console.error(`handleStartStream: 客户端不存在 ${clientId}`);
    return;
  }

  if (!rooms.has(streamId)) {
    rooms.set(streamId, {
      broadcaster: clientId,
      viewers: new Set(),
      created: new Date(),
    });

    client.rooms.add(streamId);

    client.ws.send(
      JSON.stringify({
        type: "stream-started",
        streamId: streamId,
      })
    );

    console.log(`直播开始: ${streamId} by ${clientId}`);
  } else {
    client.ws.send(
      JSON.stringify({
        type: "error",
        error: "直播间ID已存在",
      })
    );
  }
}

// 加入直播间
function handleJoinStream(clientId, message) {
  const { streamId } = message;
  console.log(`=== 处理加入直播间请求 ===`);
  console.log(`观众ID: ${clientId}`);
  console.log(`直播间ID: ${streamId}`);
  console.log(`当前房间数量: ${rooms.size}`);

  const room = rooms.get(streamId);
  const client = clients.get(clientId);

  if (!client) {
    console.error(`handleJoinStream: 客户端不存在 ${clientId}`);
    return;
  }

  console.log(`房间存在: ${!!room}`);
  if (room) {
    console.log(`主播ID: ${room.broadcaster}`);
    console.log(`当前观众数: ${room.viewers.size}`);
  }

  if (!room) {
    console.log(`直播间不存在，发送错误消息给观众: ${clientId}`);
    client.ws.send(
      JSON.stringify({
        type: "error",
        error: "直播间不存在",
      })
    );
    return;
  }

  // 添加观众到房间
  room.viewers.add(clientId);
  client.rooms.add(streamId);
  console.log(`观众已添加到房间，当前观众数: ${room.viewers.size}`);

  // 获取主播客户端
  const broadcaster = clients.get(room.broadcaster);
  console.log(`主播客户端存在: ${!!broadcaster}`);

  if (broadcaster) {
    console.log(`向主播发送create-offer请求`);
    console.log(`主播连接状态: ${broadcaster.ws.readyState}`);

    // 请求主播创建offer
    const createOfferMessage = {
      type: "create-offer",
      viewerId: clientId,
      streamId: streamId,
    };

    safeSend(broadcaster.ws, room.broadcaster, createOfferMessage);
    console.log(`create-offer消息已发送给主播 ${room.broadcaster}`);
  } else {
    console.error(`主播客户端不存在: ${room.broadcaster}`);
  }

  console.log(`观众 ${clientId} 加入直播间: ${streamId}`);
}

// 处理Offer
function handleOffer(clientId, message) {
  const { streamId, offer, viewerId } = message;
  const viewer = clients.get(viewerId);

  if (viewer) {
    viewer.ws.send(
      JSON.stringify({
        type: "offer",
        offer: offer,
        streamId: streamId,
      })
    );
  }
}

// 处理Answer
function handleAnswer(clientId, message) {
  const { streamId, answer } = message;
  const room = rooms.get(streamId);

  if (room) {
    const broadcaster = clients.get(room.broadcaster);
    if (broadcaster) {
      broadcaster.ws.send(
        JSON.stringify({
          type: "answer",
          answer: answer,
          viewerId: clientId,
        })
      );
    }
  }
}

// 处理ICE候选
function handleIceCandidate(clientId, message) {
  const { streamId, candidate } = message;
  const room = rooms.get(streamId);

  if (room) {
    // 转发ICE候选给对方
    if (room.broadcaster === clientId) {
      // 主播发送给观众
      room.viewers.forEach((viewerId) => {
        const viewer = clients.get(viewerId);
        if (viewer) {
          viewer.ws.send(
            JSON.stringify({
              type: "ice-candidate",
              candidate: candidate,
            })
          );
        }
      });
    } else {
      // 观众发送给主播
      const broadcaster = clients.get(room.broadcaster);
      if (broadcaster) {
        broadcaster.ws.send(
          JSON.stringify({
            type: "ice-candidate",
            candidate: candidate,
            viewerId: clientId,
          })
        );
      }
    }
  }
}

// 停止直播
function handleStopStream(clientId, message) {
  const { streamId } = message;
  const room = rooms.get(streamId);

  if (room && room.broadcaster === clientId) {
    // 通知所有观众直播结束
    room.viewers.forEach((viewerId) => {
      const viewer = clients.get(viewerId);
      if (viewer) {
        viewer.ws.send(
          JSON.stringify({
            type: "stream-stopped",
            streamId: streamId,
          })
        );
      }
    });

    rooms.delete(streamId);
    console.log(`直播结束: ${streamId}`);
  }
}

// 离开直播间
function handleLeaveStream(clientId, message) {
  const { streamId } = message;
  const room = rooms.get(streamId);
  const client = clients.get(clientId);

  if (!client) {
    console.error(`handleLeaveStream: 客户端不存在 ${clientId}`);
    return;
  }

  if (room && client) {
    room.viewers.delete(clientId);
    client.rooms.delete(streamId);
    console.log(`观众 ${clientId} 离开直播间: ${streamId}`);
  }
}

// 处理客户端断开连接
function handleClientDisconnect(clientId) {
  const client = clients.get(clientId);
  if (!client) return;

  // 清理用户参与的所有房间
  client.rooms.forEach((streamId) => {
    const room = rooms.get(streamId);
    if (room) {
      if (room.broadcaster === clientId) {
        // 主播断开，关闭直播间
        room.viewers.forEach((viewerId) => {
          const viewer = clients.get(viewerId);
          if (viewer) {
            viewer.ws.send(
              JSON.stringify({
                type: "stream-stopped",
                streamId: streamId,
              })
            );
          }
        });
        rooms.delete(streamId);
      } else {
        // 观众断开，从房间移除
        room.viewers.delete(clientId);
      }
    }
  });
}

// 处理聊天消息
function handleChatMessage(clientId, message) {
  console.log(`聊天消息 [${clientId}]:`, message);

  // 广播消息给所有连接的客户端
  clients.forEach((client, id) => {
    if (id !== clientId && client.ws.readyState === WebSocket.OPEN) {
      safeSend(client.ws, id, {
        type: "chat-message",
        from: clientId,
        message: message.message,
        timestamp: new Date().toISOString(),
      });
    }
  });
}

// API路由
app.get("/api/rooms", (req, res) => {
  const roomList = Array.from(rooms.entries()).map(([id, room]) => ({
    id,
    broadcaster: room.broadcaster,
    viewerCount: room.viewers.size,
    viewers: Array.from(room.viewers),
    created: room.created,
  }));

  res.json({
    totalRooms: rooms.size,
    totalClients: clients.size,
    rooms: roomList,
  });
});

// 调试API - 获取详细状态
app.get("/api/debug", (req, res) => {
  const clientList = Array.from(clients.entries()).map(([id, client]) => ({
    id,
    rooms: Array.from(client.rooms),
    connectTime: client.connectTime,
    connected: client.ws.readyState === 1,
  }));

  res.json({
    rooms: Object.fromEntries(rooms),
    clients: clientList,
    stats: {
      totalRooms: rooms.size,
      totalClients: clients.size,
      connectedClients: Array.from(clients.values()).filter(
        (c) => c.ws.readyState === 1
      ).length,
    },
  });
});

// app.get("/api/stats", (req, res) => {
//   res.json({
//     totalRooms: rooms.size,
//     totalClients: clients.size,
//     chatClients: chatWss.clients.size,
//   });
// });

// 启动服务器
const PORT = process.env.PORT || 3003;
server.listen(PORT, () => {
  console.log(`🚀 直播服务器启动成功！`);
  console.log(
    `📡 WebSocket服务器: ws://localhost:${PORT}/ws (支持WebRTC信令和聊天)`
  );
  console.log(`🌐 前端地址: http://localhost:${PORT}`);
  console.log(`📊 API接口: http://localhost:${PORT}/api/rooms`);
});

// 优雅关闭
process.on("SIGTERM", () => {
  console.log("正在关闭服务器...");
  server.close(() => {
    console.log("服务器已关闭");
    process.exit(0);
  });
});
